Pseudo C code.

typedef struct {
	uint16_t Limit;
	uint16_t Base_0_15;
	uint8_t Base_16_23;
	uint8_t Access_Byte;
	uint8_t Limit_16_19_Flags;
	uint8_t Base_24_31;
} GDT_entry;

GDT_entry GDT[16];

uint8_t UNKARRAY[] = {
	0x8,	//512k	000
	0xA,	//640k	001
	0x16,	//1408k	010
	0x26,	//2432k	011
	0x0, 	//0k	100
	0x2E,	//2944k	101
	0x0,	//0k	110
	0x2E	//2944k	111
}

uint8_t get_POS_register(int reg)
{
	board_setup_mode();
	uint8_t val = inp(0x100 + reg);
	board_enable_mode();
	retun val;
}

//DMA registers are used to keep track of the progress.
//they memorize values that can withstand a cpu reset and memory failures.
//used to report error conditions (see for eg MEM_TEST_FAIL and RESET_03)
define DMA_0_PAGE 0x87
define DMA_1_PAGE 0x83
define DMA_2_PAGE 0x81
define DMA_3_PAGE 0x82
define DMA_5_PAGE 0x8B
define DMA_6_PAGE 0x89
define DMA_7_PAGE 0x8A
define DMA_REFRESH 0x8F


//F000:12F7
void POST_52()
{
	int base_mem_size = read_bios_data(0x13);
	int tot_mem_size = read_bios_data(0x17);
	int tot_mem_segments = tot_mem_size/64;
	int base_mem_segments = base_mem_size/64;

	//skip the first segment, already tested
	tot_mem_segments--;

	GDT[9].Limit = 0xffff;
	GDT[9].Base_0_15 = 0;
	GDT[9].Base_16_23 = 0;
	GDT[9].Access_Byte = 0x93;

	GDT[12].Limit = 0xffff;
	GDT[12].Base_0_15 = 0;
	GDT[12].Base_16_23 = 0;
	GDT[12].Access_Byte = 0x93;

	outport(DMA_2_PAGE, 0);
	outport(DMA_6_PAGE, 0);
	outport(DMA_5_PAGE, 1);

	int tested_mem = 64;
	
	for(int segment=tot_mem_segments; segment>0; segment--) {

		GDT[12].Base_16_23++;
		GDT[9].Base_16_23++;
		
		//don't check for parity or channel errors
		outport(DMA_0_PAGE, 0);
	
		uint8_t reg3 = get_POS_register(3);
		reg3 &= 7;
	
		if(GDT[12].Base_16_23 >= UNKARRAY[reg3]) {
			//check for parity and channel errors
			outport(DMA_0_PAGE, 0xC0);
		}
		
		//skip video and bios memory
		if(GDT[12].Base_16_23 <= 0xA) {
			if(GDT[12].Base_16_23 >= base_mem_segments) {
				GDT[12].Base_16_23 = 0x10;
				GDT[9].Base_16_23 = 0x10;
			}
		}
	
		outport(DMA_5_PAGE, GDT[12].Base_16_23);
	
		if(GDT[9].Base_16_23 == 0xF8) {
			break;
		}
	
		if(!mem_test_segment(GDT[12],GDT[9])) {
			mem_segment_error();
			break;		
		}

		if(inport(DMA_1_PAGE) == 0x64) {
			if(!mem_test_FFFF(GDT[12],GDT[9],32768)) {
				mem_segment_error();
				break;
			}
		}

		poke(GDT[9],0,tested_mem);
		
		tested_mem += 64;
		
		//if memory is > 2MB give the user a visual feedback
		if(tested_mem >= 2048) {
			int s = segment-1;
			//if last segment or multiple of 512KB
			if(s == 0 || !(tested_mem % 512)) {
				mem_test_print(tested_mem);
			}
		}
	}
}
